package com.woniuxy.carlife.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.carlife.domain.ServiceInfo;
import com.woniuxy.carlife.domain.ServiceRoyalty;
import com.woniuxy.carlife.domain.UserServiceLike;
import com.woniuxy.carlife.dto.ServiceInfoDto;
import com.woniuxy.carlife.mapper.ServiceInfoMapper;
import com.woniuxy.carlife.mapper.ServiceRoyaltyMapper;
import com.woniuxy.carlife.minio.MinioTemplate;
import com.woniuxy.carlife.param.ServiceInfoParam;
import com.woniuxy.carlife.param.ServiceInfoPicParam;
import com.woniuxy.carlife.param.UserLikeServiceParam;
import com.woniuxy.carlife.service.ServiceInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.carlife.service.UserServiceLikeService;
import com.woniuxy.carlife.util.ServiceInfoUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.*;

/**
 * @author fx
 * @ClassName:ServiceInfoServiceImpl
 * @Description: 服务详情service实现类
 * @date 2021/4/6 20:00
 **/

@Service
public class ServiceInfoServiceImpl extends ServiceImpl<ServiceInfoMapper, ServiceInfo> implements ServiceInfoService {

    @Resource
    private MinioTemplate mt;

    @Resource
    private ServiceInfoMapper mapper;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private ServiceRoyaltyMapper royaltyMapper;

    @Resource
    private ServiceInfoUtil infoUtil;

    @Resource
    private UserServiceLikeService likeService;

    //声明个集合存放收藏量增加的服务id
    private ArrayList<Integer> ca=new ArrayList<>();

    //声明个集合存放点赞量增加了的服务id
    private ArrayList<Integer> la=new ArrayList<>();

    //声明个集合存放状态改为下架或未营业的id
    private ArrayList<Integer> down=new ArrayList<>();

    //声明个集合存放点赞了的用户id和服务id
    private ArrayList<UserLikeServiceParam> likeId=new ArrayList<>();

    //声明个集合存放取消点赞了的用户id和服务id
    private ArrayList<UserLikeServiceParam> offLikeId=new ArrayList<>();

    /**
     * 功能描述〈添加商品详情〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 11:02
     * @throws
     */
    @Override
    public boolean saveServiceInfo(ServiceInfoParam serviceInfo) throws IOException {
        ServiceInfo info = new ServiceInfo();
        //门店id
        info.setStoreId(serviceInfo.getStoreId());
        //类别id
        info.setServiceCategoryId(serviceInfo.getServiceCategoryId());
        //类别名称
        info.setServiceCategoryName(serviceInfo.getServiceCategoryName());
        //服务图标的图片，单张
        info.setServiceInfoIcon(serviceInfo.getServiceInfoIcon());
        //服务名称
        info.setServiceInfoName(serviceInfo.getServiceInfoName());
        //服务详情介绍
        info.setServiceIntroduction(serviceInfo.getServiceIntroduction());
        //服务状态(营业中/未营业/已下架)，默认为营业中
        info.setServiceInfoStatus("营业中");
        //收藏量默认为0
        info.setServiceCollect(0);
        //点赞量默认为0
        info.setServiceLike(0);
        //评分默认为0
        info.setServiceScore(0.0);
        //销售量默认为0
        info.setServiceSaleVolume(0);
        //服务原价
        info.setServiceInfoOriginalPrice(serviceInfo.getServiceInfoOriginalPrice());
        //实际售价
        info.setServiceInfoActuallyPrice(serviceInfo.getServiceInfoActuallyPrice());
        //优惠价格,原价减去实际价格获得
        info.setServiceInfoDiscountPrice
                (serviceInfo.getServiceInfoOriginalPrice()
                        .subtract(serviceInfo.getServiceInfoActuallyPrice()));
        //抽成规则
        //先根据类别id到规则表中查询
        ServiceRoyalty royalty = royaltyMapper.selectOne(new QueryWrapper<ServiceRoyalty>()
                .eq("service_category_id", serviceInfo.getServiceCategoryId()));
        info.setRoyaltyRatio(royalty.getRoyaltyRatio());
        //图文详情，可多张图片,设置进属性中
        info.setServicePictureInfo(serviceInfo.getServiecPictureInfo());
        //创建时间
        info.setServiceCreateTime(new Timestamp(new Date().getTime()));
        //执行存储操作
        int insert = mapper.insert(info);
        if (insert>0){
            //把这个对象根据id存到redis中
            //先转成json字符串
            String str = JSON.toJSONString(info);
            //存到redis中
            redisTemplate.opsForValue()
                    .set("com.woniuxy:carlife:serviceproject:serviceinfo:id:"+info.getServiceInfoId(),
                            str);
            return true;
        }
        return false;
    }

    /**
     * 功能描述〈上传服务图标〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/13 4:17
     * @throws
     */
    @Override
    public String saveServiceInfoIcon(MultipartFile serviceIcon) throws IOException {
        LocalDate id = LocalDate.now();
        StringBuffer fileName = new StringBuffer("/");
        fileName . append(id. getYear()) . append("/")
                . append(id. getMonthValue()). append("/")
                . append(id. getDayOfMonth()) . append("/")
                . append(System. currentTimeMillis());
        String type = serviceIcon. getOriginalFilename().
                substring(serviceIcon. getOriginalFilename().lastIndexOf("."));
        fileName . append(type);
        //上传后返回路径
        String pic = mt.uploadFile
                (fileName.toString(),
                        "fourstage",
                        serviceIcon.getInputStream(),
                        serviceIcon.getSize(),
                        serviceIcon.getContentType());
        return pic;
    }

    /**
     * 功能描述〈上传服务详情图片〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/13 4:21
     * @throws
     */
    @Override
    public String saveServiceInfoPic(List<MultipartFile> infoPic) throws IOException {
        //先声明个集合存放多个图片路径
        ArrayList<String> pics = new ArrayList<>();
        //循环上传
        for (MultipartFile mf : infoPic) {
            LocalDate id1 = LocalDate.now();
            StringBuffer stringBuffer = new StringBuffer("/");
            stringBuffer . append(id1. getYear()) . append("/")
                    . append(id1. getMonthValue()). append("/")
                    . append(id1. getDayOfMonth()) . append("/")
                    . append(System. currentTimeMillis());
            String type1 = mf. getOriginalFilename()
                    . substring(mf. getOriginalFilename().lastIndexOf("."));
            stringBuffer . append(type1);
            //上传后返回路径
            String picUrl = mt.uploadFile
                    (stringBuffer.toString(),
                            "fourstage",
                            mf.getInputStream(),
                            mf.getSize(),
                            mf.getContentType());
            //将路径存放到集合中
            pics.add(picUrl);
        }
        //上传完成后将存放图片地址的集合转换为JSON字符串类型
        String string = JSON.toJSONString(pics);
        return string;
    }

    /**
     * 功能描述〈根据门店id查看服务详情〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:04
     * @throws
     */
    @Override
    public List<ServiceInfoDto> findServiceInfoByStoreId(Integer storeId){
        //根据门店id查询门店下的所有服务
        List<ServiceInfo> store_id = mapper.selectList
                (new QueryWrapper<ServiceInfo>()
                        .eq("store_id", storeId));
        List<ServiceInfoDto> serviceInfoDtos = infoUtil.infoToDtoList(store_id);
        return serviceInfoDtos;
    }

    /**
     * 功能描述〈根据门店id获得已上架的服务详情〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:04
     * @throws
     */
    @Override
    public List<ServiceInfoDto> findServcieInfoByStoreIdAndAlreadyUp(Integer storeId){
        List<ServiceInfo> serviceInfos = mapper.selectList
                (new QueryWrapper<ServiceInfo>()
                        .notIn("service_info_status", "下架"));
        List<ServiceInfoDto> serviceInfoDtos = infoUtil.infoToDtoList(serviceInfos);
        return serviceInfoDtos;
    }

    /**
     * 功能描述〈根据门店id查询营业中的服务详情〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:08
     * @throws
     */
    @Override
    public List<ServiceInfoDto> findServcieInfoByStoreIdAndDoing(Integer storeId){
        List<ServiceInfo> serviceInfos = mapper.selectList
                (new QueryWrapper<ServiceInfo>()
                        .eq("service_info_status", "营业"));
        List<ServiceInfoDto> serviceInfoDtos = infoUtil.infoToDtoList(serviceInfos);
        return serviceInfoDtos;
    }

    /**
     * 功能描述〈根据门店id查询未营业的服务详情〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:09
     * @throws
     */
    @Override
    public List<ServiceInfoDto> findServcieInfoByStoreIdAndNotDoing(Integer storeId){
        List<ServiceInfo> serviceInfos = mapper.selectList
                (new QueryWrapper<ServiceInfo>()
                        .eq("service_info_status", "未营业"));
        List<ServiceInfoDto> serviceInfoDtos = infoUtil.infoToDtoList(serviceInfos);
        return serviceInfoDtos;
    }

    /**
     * 功能描述〈根据服务id查询指定服务详情〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:05
     * @throws
     */
    @Override
    public ServiceInfoDto findServcieInfoByServiceInfoId(Integer infoId){
        //先找reids
        String o = (String) redisTemplate.opsForValue()
                .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId);
        //判断是否有数据
        if (ObjectUtils.isEmpty(o)){
            //没数据就找数据库
            ServiceInfo info = mapper.selectOne(new QueryWrapper<ServiceInfo>()
                                    .eq("service_info_id",infoId));
            ServiceInfoDto serviceInfoDto = infoUtil.infoToDtoOne(info);
//            //存redis
//            String string = JSON.toJSONString(info);
//            redisTemplate.opsForValue()
//                    .set("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId,
//                            string);
            return serviceInfoDto;
        }
        //有数据就转换成对象
        ServiceInfo info = JSON.parseObject(o, ServiceInfo.class);
        ServiceInfoDto serviceInfoDto = infoUtil.infoToDtoOne(info);
        return serviceInfoDto;
    }

    /**
     * 功能描述〈根据服务id增加服务收藏量redis〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:05
     * @throws
     */
    @Override
    public Boolean updateUpServcieInfoCollectByServiceInfoIdToRedis(Integer infoId){
        //先从redis查
        String o = (String) redisTemplate.opsForValue()
                .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId);
        ServiceInfo info;
        //判断是否有数据
        if (ObjectUtils.isEmpty(o)){
            //没数据就找数据库
            info = mapper.selectById(infoId);
        }else{
            //有数据就转换成对象
            info = JSON.parseObject(o, ServiceInfo.class);
        }
        //再判断从两个地方查到的数据是否为空，就是判断传入的详情id是否有效
        if (ObjectUtils.isEmpty(info)){
            //为空直接返回false
            return false;
        }
        //把收藏量+1
        info.setServiceCollect(info.getServiceCollect()+1);
        //添加收藏量集合
        ca.add(info.getServiceInfoId());
        //存redis
        String string = JSON.toJSONString(info);
        redisTemplate.opsForValue()
                .set("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId,
                        string);
        return true;
    }

    /**
     * 功能描述〈根据服务id减少收藏量redis〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:06
     * @throws
     */
    @Override
    public Boolean updateDownServcieInfoCollectByServiceInfoIdToRedis(Integer infoId){
        //先从redis查
        String o = (String) redisTemplate.opsForValue()
                .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId);
        ServiceInfo info;
        //判断是否有数据
        if (ObjectUtils.isEmpty(o)){
            //没数据就找数据库
            info = mapper.selectById(infoId);
        }else{
            //有数据就转换成对象
            info = JSON.parseObject(o, ServiceInfo.class);
        }
        //再判断从两个地方查到的数据是否为空，就是判断传入的详情id是否有效
        if (ObjectUtils.isEmpty(info)){
            //为空直接返回false
            return false;
        }
        //把收藏量-1
        info.setServiceCollect(info.getServiceCollect()-1);
        //从收藏量集合删除
        ca.remove(info.getServiceInfoId());
        //存redis
        String string = JSON.toJSONString(info);
        redisTemplate.opsForValue()
                .set("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId,
                        string);
        return true;
    }

    /**
     * 功能描述〈根据服务id增加或减少点赞量redis〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:06
     * @throws
     */
    @Override
    public Boolean updateUpServcieInfoLikeByServiceInfoIdToRedis(UserLikeServiceParam like){
        //先从redis查
        String o = (String) redisTemplate.opsForValue()
                .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + like.getServiceId());
        ServiceInfo info;
        //判断是否有数据
        if (ObjectUtils.isEmpty(o)){
            //没数据就找数据库
            info = mapper.selectById(like.getServiceId());
        }else{
            //有数据就转换成对象
            info = JSON.parseObject(o, ServiceInfo.class);
        }
        //再判断从两个地方查到的数据是否为空，就是判断传入的详情id是否有效
        if (ObjectUtils.isEmpty(info)){
            System.out.println("没查到服务数据");
            //为空直接返回false
            return false;
        }
        //调用用户关联服务点赞表的service方法
        String s = likeService.updateLikeToOffByUserIdAndServiceId(like);
        if (s.equals("错误")){
            return false;
        }else if (s.equals("点赞")){
            System.out.println(like.getUserId()+"点赞");
            //把点赞量+1
            info.setServiceLike(info.getServiceLike()+1);
            //添加点赞量集合
            la.add(info.getServiceInfoId());
            //点赞表集合存对象
            //循环判断是否是同一个用户和服务
            for (UserLikeServiceParam u : offLikeId) {
                if (u.getUserId()==like.getUserId()&&u.getServiceId()==like.getServiceId()){
                    offLikeId.remove(like);
                    break;
                }
            }
            likeId.add(like);
        }else if (s.equals("取消点赞")){
            System.out.println(like.getUserId()+"取消点赞");
            //把点赞量-1
            info.setServiceLike(info.getServiceLike()-1);
            //从点赞量集合移除
            la.remove(info.getServiceInfoId());
            //循环判断是否是同一个用户和服务
            for (UserLikeServiceParam u : likeId) {
                if (u.getUserId()==like.getUserId()&&u.getServiceId()==like.getServiceId()){
                    //点赞表集合删数据
                    likeId.remove(like);
                    break;
                }
            }
            //不是之前有的话就添加到集合
            offLikeId.add(like);
        }
        //存redis
        String string = JSON.toJSONString(info);
        redisTemplate.opsForValue()
                .set("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + like.getServiceId(),
                        string);
        return true;
    }
//    /**
//     * 功能描述〈根据服务id减少点赞量redis〉
//     * @author:fx
//     * @param: @param null:
//     * @return:
//     * @Date 2021/4/12 12:06
//     * @throws
//     */
//    @Override
//    public Boolean updateDownServcieInfoLikeByServiceInfoIdToRedis(Integer infoId){
//        //先从redis查
//        String o = (String) redisTemplate.opsForValue()
//                .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId);
//        ServiceInfo info;
//        //判断是否有数据
//        if (ObjectUtils.isEmpty(o)){
//            //没数据就找数据库
//            info = mapper.selectById(infoId);
//        }else{
//            //有数据就转换成对象
//            info = JSON.parseObject(o, ServiceInfo.class);
//        }
//        //再判断从两个地方查到的数据是否为空，就是判断传入的详情id是否有效
//        if (ObjectUtils.isEmpty(info)){
//            //为空直接返回false
//            return false;
//        }
//
//        //存redis
//        String string = JSON.toJSONString(info);
//        redisTemplate.opsForValue()
//                .set("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId,
//                        string);
//        return true;
//    }

    /**
     * 功能描述〈根据服务id修改服务状态为营业中〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:06
     * @throws
     */
    @Override
    public Boolean updateServiceInfoStatusToDoing(Integer infoId){
        ServiceInfo info = new ServiceInfo();
        info.setServiceInfoId(infoId);
        info.setServiceInfoStatus("营业");
        int i = mapper.updateById(info);
        if (i>0){
            //在查一次信息
            ServiceInfo info1 = mapper.selectById(infoId);
            //存redis
            String string = JSON.toJSONString(info);
            redisTemplate.opsForValue()
                    .set("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId,
                            string);
            //存储不是营业中的集合中删除这个id
            if (down.contains(infoId)){
                down.remove(infoId);
            }
            return true;
        }
        return false;
    }

    /**
     * 功能描述〈根据服务id修改服务状态为未营业〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:07
     * @throws
     */
    @Override
    public Boolean updateServiceInfoStatusToNotDoing(Integer infoId){
        //先从redis查
        String o = (String) redisTemplate.opsForValue()
                .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId);
        //判断是否有数据
        if (!ObjectUtils.isEmpty(o)){
            //有数据就保存这个id，定时任务删除这个key
            down.add(infoId);
        }
        //声明一个对象
        ServiceInfo info = new ServiceInfo();
        info.setServiceInfoId(infoId);
        info.setServiceInfoStatus("营业");
        //改状态
        int i = mapper.updateById(info);
        if (i>0){
            return true;
        }
        return false;
    }

    /**
     * 功能描述〈下架服务〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:10
     * @throws
     */
    @Override
    public Boolean updateServiceInfoStatusToDown(Integer infoId){
        //先从redis查
        String o = (String) redisTemplate.opsForValue()
                .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + infoId);
        //判断是否有数据
        if (!ObjectUtils.isEmpty(o)){
            //有数据就保存这个id，定时任务删除这个key
            down.add(infoId);
        }
        //声明一个对象
        ServiceInfo info = new ServiceInfo();
        info.setServiceInfoId(infoId);
        info.setServiceInfoStatus("下架");
        //改状态
        int i = mapper.updateById(info);
        if (i>0){
            return true;
        }
        return false;
    }

    /**
     * 功能描述〈修改收藏量、点赞量、销售量到数据库，定时任务〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 12:10
     * @throws
     */
    @Override
    public Boolean updateServcieInfoCollectByServiceInfoIdToSql(){
        //循环遍历收藏量集合
        for (Integer id : ca) {
            //从redis中依次取值
            String o = (String) redisTemplate.opsForValue()
                    .get("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + id);
            //转换成对象
            ServiceInfo info = JSON.parseObject(o, ServiceInfo.class);
            ServiceInfo info1 = new ServiceInfo();
            //id
            info1.setServiceInfoId(id);
            //收藏量
            info1.setServiceCollect(info.getServiceCollect());
            //点赞量
            info1.setServiceLike(info.getServiceLike());
            //销售量
            info1.setServiceSaleVolume(info1.getServiceSaleVolume());
            //修改时间
            info1.setServiceUpdateTime(new Timestamp(new Date().getTime()));
            //修改以上数据
            mapper.updateById(info1);
        }
        //循环设置为下架的服务id集合，
        // 把服务id从redis中状态为上架的key中删除，下架了就不需要点赞了
        for (Integer integer : down) {
            redisTemplate
                    .delete("com.woniuxy:carlife:serviceproject:serviceinfo:id:" + integer);
            //再把统计服务评论的key也删除，下架了也不能评价了
            redisTemplate
                    .delete("com.woniuxy:carlife:serviceproject:serviceappraisescore:serviceid:"
                            + integer);
        }
        //调用关联表实现类方法，将做了点赞的集合，修改到数据库
        likeService.updateLikeStatusByUserIdAndServiceIdToSql(likeId);
        //集合清空
        likeId.clear();
        //调用关联表实现类方法，将做了取消点赞的集合，修改到数据库
        likeService.updateOffLikeStatusByUserIdAndServiceIdToSql(offLikeId);
        //集合清空
        offLikeId.clear();
        //将三个集合中的数据清空
        ca.clear();
        la.clear();
        down.clear();
        return true;
    }

    /**
     * 功能描述〈修改服务图片〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/14 16:55
     * @throws
     */
    @Override
    public Boolean updateServiceInfoIcon(ServiceInfoPicParam picParam) {
        ServiceInfo info = new ServiceInfo();
        info.setServiceInfoId(picParam.getInfoId());
        info.setServiceInfoIcon(picParam.getPic());
        int i = mapper.updateById(info);
        if (i>0){
            return true;
        }
        return false;
    }

    /**
     * 功能描述〈修改服务详情图片〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/14 16:56
     * @throws
     */
    @Override
    public Boolean updateServiceInfoPic(ServiceInfoPicParam picParam) {
        ServiceInfo info = new ServiceInfo();
        info.setServiceInfoId(picParam.getInfoId());
        info.setServicePictureInfo(picParam.getPic());
        int i = mapper.updateById(info);
        if (i>0){
            return true;
        }
        return false;
    }

    /**
     * 功能描述〈修改销量redis〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 13:36
     * @throws
     */
    @Override
    public Boolean updateServcieInfoSaleByServiceInfoIdToRedis() {
        return null;
    }

}
